﻿/*
 * Author: Thomas Mattsson
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Final_Project
{
    /// <summary>
    /// This class handles inputs from the user.
    /// </summary>
    class InputUtility
    {
        /// <summary>
        /// Converts a string-represented Double value into a Double type, and validates
        /// the converted value to be within (and inclusive) a range, defined by minLimit and
        /// maxLimit.
        /// </summary>
        /// <param name="toParse">string representing a Double value.</param>
        /// <param name="dblOutValue">output parameter, the converted Double value.</param>
        /// <param name="minLimit">The output value should be greater or equal to minLimit.</param>
        /// <param name="maxLimit">The output value should be less than or equal to maxLimit.</param>
        /// <returns>true if the conversion is successful and the converted value is within the given range</returns>
        public static bool GetDouble(string toParse, out double dblOutValue, double minLimit, double maxLimit)
        {
            // Initialize variable
            dblOutValue = -1;

            // Fix comma and dot issue
            string newText = toParse.Replace(".", ",");

            bool okInput = double.TryParse(newText, out dblOutValue);

            return (okInput && (dblOutValue >= minLimit) && (dblOutValue <= maxLimit));
        }

        /// <summary>
        /// Converts a string-represented Double value into a Double type, and validates
        /// the converted value to be within (and inclusive) a range, defined by minLimit and
        /// the upper limit of the Double type.
        /// </summary>
        /// <param name="toParse">string representing a Double value.</param>
        /// <param name="dblOutValue">output parameter, the converted Double value.</param>
        /// <param name="minLimit">The output value should be greater or equal to minLimit.</param>
        /// <returns>true if the conversion is successful and the converted value is greater or equal to minLimit</returns>
        public static bool GetDouble(string toParse, out double dblOutValue, double minLimit)
        {
            return GetDouble(toParse, out dblOutValue, minLimit, double.MaxValue);
        }


        /// <summary>
        /// Converts a string-represented Double value into a Double type, and validates
        /// the converted value to be within (and inclusive) a range, defined by the Double type.
        /// </summary>
        /// <param name="toParse">string representing a Double value.</param>
        /// <param name="dblOutValue">output parameter, the converted Double value.</param>
        /// <returns>true if the conversion is successful and the converted value is greater or equal to minLimit</returns>
        public static bool GetDouble(string toParse, out double dblOutValue)
        {
            return GetDouble(toParse, out dblOutValue, double.MinValue, double.MaxValue);
        }


        /// <summary>
        /// Converts a string-represented Integer value into a Integer type, and validates
        /// the converted value to be within (and inclusive) a range, defined by minLimit and
        /// maxLimit. 
        /// </summary>
        /// <param name="toParse">string representing a Integer value.</param>
        /// <param name="intOutValue">output value, the converted Integer value</param>
        /// <param name="minLimit">The output value should be greater than or equal to minLimit.</param>
        /// <param name="maxLimit">The output value should be less than or equal to maxLimit.</param>
        /// <returns>true if the conversion is successful and the converted value is within the given range</returns>
        public static bool GetInteger(string toParse, out int intOutValue, int minLimit, int maxLimit)
        {
            bool okInput = int.TryParse(toParse, out intOutValue);
            return (okInput && (intOutValue >= minLimit) && (intOutValue <= maxLimit));
        }


        /// <summary>
        /// Converts a string-represented Integer value into a Integer type, and validates
        /// the converted value to be within (and inclusive) a range, defined by the minValue and
        /// the upper limit of the Integer type.
        /// </summary>
        /// <param name="toParse">string representing a Integer value.</param>
        /// <param name="intOutValue">output value, the converted Integer value</param>
        /// <param name="minLimit">The output value should be greater than or equal to minLimit.</param>
        /// <returns>true if the conversion is successful and the converted value is within the given range</returns>
        public static bool GetInteger(string toParse, out int intOutValue, int minLimit)
        {
            return GetInteger(toParse, out intOutValue, minLimit, int.MaxValue);
        }


        /// <summary>
        /// Converts a string-represented Integer value into a Integer type, and validates
        /// the converted value to be within (and inclusive) a range, defined by the Integer type.
        /// </summary>
        /// <param name="toParse">string representing a Integer value.</param>
        /// <param name="intOutValue">output value, the converted Integer value</param>
        /// <returns>true if the conversion is successful and the converted value is within the given range</returns>
        public static bool GetInteger(string toParse, out int intOutValue)
        {
            return GetInteger(toParse, out intOutValue, int.MinValue, int.MaxValue);
        }


        /// <summary>
        /// This method checks if a string is a valid email address.
        /// </summary>
        /// <param name="toParse">The string to check.</param>
        /// <param name="validEmail">String containing valid email string or empty string.</param>
        /// <returns>True if email is ok, False otherwise.</returns>
        public static bool GetEmail(string toParse, out string validEmail) {
            validEmail = string.Empty;
            toParse = toParse.Trim();

            bool result = (LegitNameBeforeAt(toParse) &&
                           LegitLengthOfDomainName(toParse) &&
                           LegitCountrySuffix(toParse));

            if (result)
            {
                // String seems fine, assign it to validEmail variable.
                validEmail = toParse;
                return true;
            }
            return false;
        }

        /// <summary>
        /// This method checks that the string before '@' character
        /// has a length of 3 or more characters. Else it is considered
        /// a bad email name.
        /// </summary>
        /// <param name="address">The string to check</param>
        /// <returns>True if string is ok, False otherwise.</returns>
        private static bool LegitNameBeforeAt(string address)
        {
            int at = address.IndexOf("@");
            return (at >= 3);
        }


        /// <summary>
        /// This method checks that the domain part of the 
        /// address is at least 3 characters long.
        /// </summary>
        /// <param name="address">The string to check.</param>
        /// <returns>True if domain is at least 3 chars long, False otherwise.</returns>
        private static bool LegitLengthOfDomainName(string address)
        {
            int lastDot = address.LastIndexOf(".");
            int at = address.IndexOf("@");
            return ((lastDot - at) >= 3);
        }

        
        /// <summary>
        /// This method checks that the country suffix of an address
        /// has at least 2 characters and at most 4 characters (.info addresses)
        /// </summary>
        /// <param name="address">The address to check</param>
        /// <returns>True if suffix is ok, False otherwise.</returns>
        private static bool LegitCountrySuffix(string address)
        {
            int lastIndex = address.Length - 1;
            int lastDot = address.LastIndexOf(".");
            int suffixLength = lastIndex - lastDot;
            return (suffixLength >= 2 && suffixLength <= 4);
        }
    }
}
